package com.xwaiy.xwaiyrpc.loadbalancer;

import com.xwaiy.xwaiyrpc.model.ServiceMetaInfo;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 一致性哈希负载均衡器
 * @Author Xwaiy
 * @Date 2025/9/2 17:06
 **/
public class HashLoadBalancer implements LoadBalancer{

    // 虚拟节点
    private final TreeMap<Integer, ServiceMetaInfo> nodes = new TreeMap<>();

    // 虚拟节点数
    private static final int VIRTUAL_NODE_NUM = 100;

    @Override
    public ServiceMetaInfo select(Map<String, Object> params, List<ServiceMetaInfo> list) {
        if(list.isEmpty()){
            return null;
        }

        for(ServiceMetaInfo info : list){
            for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
                int hashCode = getHashCode(info.getServiceAddress()+"_"+i);
                nodes.put(hashCode, info);
            }
        }

        // 从参数中获取客户端IP地址来计算Hash值
        String clientIp = getClientIpFromParams(params);
        int hashCode = getHashCode(clientIp);

        Map.Entry<Integer, ServiceMetaInfo> entry = nodes.ceilingEntry(hashCode);

        if(entry == null){
            entry = nodes.firstEntry();
        }

        return entry.getValue();
    }

    /**
     * 从参数中提取客户端IP地址
     */
    private String getClientIpFromParams(Map<String, Object> params) {
        if (params == null) {
            return "unknown";
        }
        // 尝试从常见的关键字中获取IP地址
        String[] ipKeys = {"clientIp", "ip", "remoteIp", "clientAddress", "remoteAddress"};

        for (String key : ipKeys) {
            Object value = params.get(key);
            if (value != null && value instanceof String) {
                String ip = ((String) value).trim();
                if (!ip.isEmpty()) {
                    return ip;
                }
            }
        }
        // 如果找不到明确的IP参数，使用默认值
        return "default_client";
    }

    /**
     * 自定义哈希算法 - 基于客户端IP
     */
    private int getHashCode(Object key){
        if (key == null) {
            return 0;
        }
        String str = key.toString();
        int hash = 0;

        for (int i = 0; i < str.length(); i++) {
            hash = 31 * hash + str.charAt(i);
        }
        // 确保哈希值为正数
        return hash & 0x7FFFFFFF;
    }
}